<template>
	<div class="container" :style="{ ...container }">
		<div
			class="title-container"
			v-if="props.config.style.titleShow"
			:style="{ justifyContent: props.config.style.align }"
		>
			<div class="flex items-center">
				<i
					:class="['iconfont', props.config.style.titleIcon]"
					:style="{ ...titleIconStyle }"
					v-if="props.config.style.titleIconShow"
				></i>
				<span class="font-7" :style="{ ...titleStyle }">{{ props.config.style.title }}</span>
			</div>
			<div class="flex items-center" v-if="props.config.style.titleEndShow">
				<span class="font-7" :style="{ ...titleEndStyle }">{{ props.config.style.titleEnd }}</span>
				<i
					:class="['iconfont', props.config.style.titleEndIcon]"
					:style="{ ...titleEndIconStyle }"
					v-if="props.config.style.titleEndIconShow"
				></i>
			</div>
		</div>
		<div ref="chartContainer" class="chart-container"></div>
	</div>
</template>

<script setup>
	import config from './config'
	import { ref, onMounted, onBeforeUnmount, nextTick, computed, watch, reactive } from 'vue'
	import { Area } from '@antv/g2plot'
	import { cloneDeep, merge } from 'lodash-es'
	import datasetApi from '@/views/plugin/dashboard/api/datasetApi'
	import { observeChartResize, updateChart, cleanupChart } from '@/views/plugin/dashboard/plugin/utils/chartUtils'

	const emit = defineEmits(['update:config'])
	const props = defineProps({
		config: {
			type: Object,
			default: () => config
		}
	})

	const chartContainer = ref(null)
	const chartInstance = ref(null)
	const resizeObserver = ref(null)
	// 数据源数据
	const chartData = ref({})
	// 旧的dataSetJson 用于比较是否一样就不重新获取数据
	const oldDataSetJson = ref(props.config.dataSetConfig.dataSetJson)
	// 图表配置
	const chartOptions = ref({})

	// 获取数据源数据函数
	const fetchChartData = async (isFlag = false) => {
		const { dataSetType, dataSetJson } = props.config.dataSetConfig
		const isNew = isFlag || JSON.stringify(oldDataSetJson.value) !== JSON.stringify(dataSetJson)
		chartData.value = props.config.data.chartData.value || []
		// 如果是静态数据
		if (dataSetType === 0) return
		// 如果是数据源且有效
		if (dataSetType === 1 && dataSetJson && Object.keys(dataSetJson).length > 0 && isNew) {
			// 更新值
			oldDataSetJson.value = dataSetJson
			// 模拟接口返回下拉数据
			await datasetApi.preview(dataSetJson).then((res) => {
				chartData.value = res
			})
			return
		}
	}

	// 设置图表配置
	const setChartOptions = () => {
		const baseOptions = {
			data: chartData.value || [],
			xField: props.config.data.xField.field,
			yField: props.config.data.yField.field,
			seriesField: props.config.data.seriesField.field,
			color: props.config.style.chartColor,
			smooth: props.config.style.smooth,
			point: props.config.style.showPoint
				? {
						size: 4,
						shape: 'circle',
						style: {
							fill: 'white',
							stroke: '#5B8FF9',
							lineWidth: 2
						}
					}
				: false,
			legend: props.config.style.showLegend
				? {
						position: props.config.style.legendPosition
					}
				: false,
			xAxis: {
				label: {
					autoHide: true,
					autoRotate: false
				}
			},
			yAxis: {
				label: {
					// 数值格式化为千分位
					formatter: (v) => `${v}`.replace(/\d{1,3}(?=(\d{3})+$)/g, (s) => `${s},`)
				}
			},
			interactions: [{ type: 'element-active' }]
		}

		// 根据图表类型添加特定配置
		switch (props.config.style.chartType) {
			case 'stack':
				chartOptions.value = merge({}, baseOptions, {
					isStack: true,
					isPercent: false,
					meta: {
						value: {
							formatter: (v) => {
								return v
							}
						}
					}
				})
				break
			case 'percent':
				chartOptions.value = merge({}, baseOptions, {
					isStack: true,
					isPercent: true,
					meta: {
						value: {
							formatter: (v) => {
								return `${(v * 100).toFixed(2)}%`
							}
						}
					}
				})
				break
			default: // basic
				chartOptions.value = merge({}, baseOptions, {
					isStack: false,
					isPercent: false,
					meta: {
						value: {
							formatter: (v) => {
								return v
							}
						}
					}
				})
				return
		}
	}

	// 初始化图表
	const initChart = async () => {
		await nextTick()
		if (chartContainer.value && !chartInstance.value) {
			chartInstance.value = new Area(chartContainer.value, chartOptions.value)
			chartInstance.value.render()
		}
	}

	// 监听配置变化，更新图表
	// watch(
	// 	() => props.config,
	// 	() => {
	// 		if (chartInstance.value) {
	// 			setChartOptions()
	// 			chartInstance.value.update(chartOptions.value)
	// 		}
	// 	},
	// 	{ deep: true }
	// )

	// 暴露给外部的更新配置方法
	const onReload = async (isFlag = false) => {
		// 获取数据
		await fetchChartData(isFlag)
		// 初始化图表配置
		setChartOptions()
		console.log('chartOptions.value', chartOptions.value)
		// 更新图表
		if (chartInstance.value) {
			await nextTick(() => {
				updateChart(chartInstance.value, chartOptions.value)
			})
		} else {
			await initChart()
		}
	}

	onMounted(async () => {
		// 初始化图表配置
		await onReload()
		// 监听容器尺寸变化，使外层卡片拖动时图表能更新
		if (chartContainer.value) {
			resizeObserver.value = observeChartResize(chartContainer.value, chartInstance.value, resizeObserver.value)
		}
	})

	// 暴露方法给父组件
	defineExpose({
		onReload
	})

	// 组件卸载前清理
	onBeforeUnmount(() => {
		// 使用通用方法清理图表资源
		cleanupChart(chartInstance.value, resizeObserver.value)
	})

	// 样式计算
	const container = computed(() => ({
		backgroundColor: props.config.style.bgColor,
		backgroundImage: props.config.style.bgImg ? `url(${props.config.style.bgImg})` : 'none',
		borderStyle: props.config.style.borderStyle,
		borderColor: props.config.style.borderColor,
		borderWidth: props.config.style.borderWidth + 'px',
		paddingTop: props.config.style.paddingT + 'px',
		paddingRight: props.config.style.paddingR + 'px',
		paddingBottom: props.config.style.paddingB + 'px',
		paddingLeft: props.config.style.paddingL + 'px',
		borderTopLeftRadius: props.config.style.bgRTL + 'px',
		borderTopRightRadius: props.config.style.bgRTR + 'px',
		borderBottomLeftRadius: props.config.style.bgRBL + 'px',
		borderBottomRightRadius: props.config.style.bgRBR + 'px',
		boxShadow: `${props.config.style.shadowX}px ${props.config.style.shadowY}px ${props.config.style.shadowDegree}px ${props.config.style.shadowColor}`,
		position: 'relative' // 为了定位确认和重置按钮
	}))

	const titleStyle = computed(() => ({
		fontSize: props.config.style.titleSize + 'px',
		color: props.config.style.titleColor,
		fontWeight: props.config.style.titleWeight ? 'bold' : 'normal',
		fontStyle: props.config.style.titleStyle ? 'italic' : 'normal',
		textDecoration: props.config.style.titleLine ? 'underline' : 'none'
	}))

	const titleIconStyle = computed(() => ({
		fontSize: props.config.style.titleIconSize + 'px',
		color: props.config.style.titleIconColor,
		marginRight: '5px'
	}))

	const titleEndStyle = computed(() => ({
		fontSize: props.config.style.titleEndSize + 'px',
		color: props.config.style.titleEndColor,
		fontWeight: props.config.style.titleEndWeight ? 'bold' : 'normal',
		fontStyle: props.config.style.titleEndStyle ? 'italic' : 'normal',
		textDecoration: props.config.style.titleEndLine ? 'underline' : 'none'
	}))

	const titleEndIconStyle = computed(() => ({
		fontSize: props.config.style.titleEndIconSize + 'px',
		color: props.config.style.titleEndIconColor,
		marginLeft: '5px'
	}))
</script>

<style scoped lang="less">
	.container {
		height: 100%;
		width: 100%;
		display: flex;
		flex-direction: column;
	}

	.title-container {
		display: flex;
		align-items: center;
		margin-bottom: 10px;
	}

	.chart-container {
		flex: 1;
		width: 100%;
		min-height: 100px;
	}

	// 确认和重置按钮样式
	.action-buttons {
		position: absolute;
		top: 10px;
		right: 10px;
		z-index: 10;
		display: flex;
		gap: 8px;
	}

	.confirm-btn,
	.reset-btn {
		padding: 4px 12px;
		border-radius: 2px;
		font-size: 12px;
		cursor: pointer;
		border: none;
		transition: all 0.3s;
	}

	.confirm-btn {
		background-color: #1890ff;
		color: white;

		&:hover {
			background-color: #40a9ff;
		}
	}

	.reset-btn {
		background-color: #f0f0f0;
		color: #333;

		&:hover {
			background-color: #d9d9d9;
		}
	}
</style>
